﻿using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using kbd.library.helper;

namespace DataServiceInterception
{
    public class DataServiceTest
    {
        public void Start()
        {

            logger.Log(LogLevels.Information, "[Stating DataServiceTest] ************************************ ");
            logger.Log(LogLevels.Information, "");

            string serviceAddress = "http://localhost:998";
            Uri[] uriArray = { new Uri(serviceAddress) };
            Type serviceType = typeof(CustomerDataService);

            using (var host = new DataServiceHost(serviceType, uriArray))
            {
                host.Open();

                #region HOST INFORMATION
                // svcDesc is a ServiceDescription.
                var svcDesc = host.Description;
                string configName = svcDesc.ConfigurationName;
                logger.Log(LogLevels.Information, String.Format("Configuration name: {0}", configName));

                // Iterate through the endpoints contained in the ServiceDescription
                ServiceEndpointCollection sec = svcDesc.Endpoints;
                foreach (ServiceEndpoint se in sec)
                {
                    logger.Log(LogLevels.Information, "Endpoint:");
                    logger.Log(LogLevels.Information, String.Format("\tAddress: {0}", se.Address.ToString()));
                    logger.Log(LogLevels.Information, String.Format("\tBinding: {0}", se.Binding.ToString()));
                    logger.Log(LogLevels.Information, String.Format("\tContract: {0}", se.Contract.ToString()));
                    KeyedByTypeCollection<IEndpointBehavior> behaviors = se.Behaviors;
                    foreach (IEndpointBehavior behavior in behaviors)
                    {
                        logger.Log(LogLevels.Information, String.Format("Behavior: {0}", behavior.ToString()));
                    }
                }

                string name = svcDesc.Name;
                logger.Log(LogLevels.Information, String.Format("Service Description name: {0}", name));

                string namespc = svcDesc.Namespace;
                logger.Log(LogLevels.Information, String.Format("Service Description namespace: {0}", namespc));

                Type serviceType2 = svcDesc.ServiceType;
                logger.Log(LogLevels.Information, String.Format("Service Type: {0}", serviceType2.ToString()));

                // The service can now be accessed.
                logger.Log(LogLevels.Information, "The service is ready.");
                #endregion

                logger.Log(LogLevels.Information, "Press any key to stop service");
                Console.ReadKey();
            }

        }
    }

    // Expose IQueryable properties as read-only Atom collections
    public class CustomerDataService : DataService<CustomerService>
    {

        #region These elements will allow us to parse the query string for non oData elements
        
        DataServiceOperationContext OpsContext;
        Dictionary<string, string> QueryParameters;

        /// <summary>
        /// GetQueryParameterBag
        /// </summary>
        /// <param name="serviceOperationContext"></param>
        /// <returns></returns>
        Dictionary<string, string> GetQueryParameterBag(DataServiceOperationContext serviceOperationContext)
        {
            Dictionary<string, string> ParameterBag = null;
            string query = serviceOperationContext.AbsoluteRequestUri.Query;

            if (!string.IsNullOrEmpty(query))
            {
                ParameterBag = new Dictionary<string, string>();
                query = query.Remove(0, 1);
                string[] param = query.Split('&');

                string paramName;
                string paramValue;

                foreach (var item in param)
                {
                    //Skip OData supported parameters 
                    if (!item.StartsWith("$"))
                    {
                        paramName = item.Substring(0, item.IndexOf("="));
                        paramValue = item.Substring(item.IndexOf("=") + 1);
                        ParameterBag.Add(paramName, paramValue);
                    }
                }
            }
            return ParameterBag;
        }


        #endregion

        #region Data Service Initialize Service

        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        }
        #endregion

        protected override void OnStartProcessingRequest(ProcessRequestArgs args)
        {
            OpsContext = args.OperationContext;
            QueryParameters = GetQueryParameterBag(OpsContext);
            logger.Log(LogLevels.Medium, String.Format("OnStartProcessingRequest: {0}", OpsContext.AbsoluteRequestUri));
            base.OnStartProcessingRequest(args);
        }

        public IQueryable<Customer> Customers()
        {
            logger.Log(LogLevels.Medium, String.Format("IQueryable<Customer> Customers"));
            return this.CurrentDataSource.Customers;
        }

    }




}
